package com.example.avplayer;

import android.hardware.display.DisplayManager;
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
import android.media.MediaFormat;
import android.media.projection.MediaProjection;
import android.os.Environment;
import android.view.Surface;

import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;

public class H264Encoder extends Thread{

    private MediaProjection mediaProjection;

    private MediaCodec mediaCodec;
    private int width;
    private int height;
    public H264Encoder(MediaProjection mediaProjection) {
        this.mediaProjection = mediaProjection;
        this.width = 1080;
        this.height = 1920;
        try {
            mediaCodec = MediaCodec.createEncoderByType("video/avc");

            MediaFormat mediaFormat = MediaFormat.createVideoFormat(MediaFormat.MIMETYPE_VIDEO_AVC,width,height);
            // 帧率 1m  20帧
            mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE,20);
            // 30帧 生成一个I帧
            mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL,30);
            // 码率 码率一般指比特率,是表示单位时间内传送比特的数目。单位为比特/秒(bit/s或bps)
            mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE,width*height);
            // 设置颜色格式
            mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
            mediaCodec.configure(mediaFormat,null,null,MediaCodec.CONFIGURE_FLAG_ENCODE);
            Surface inputSurface = mediaCodec.createInputSurface();
            //  创建虚拟屏幕
//            name：为本地用来存储录屏内容的MP4文件路径
//            width：录下来的视频的水平像素数，需要和屏幕宽度（指像素数，而不是物理宽度）保持一致，小于屏幕宽度会导致有黑边填充，大于屏幕宽度会导致手机死机。
//            height：视频高度，需与屏幕高度一致。
//            dpi：宽高固定之后该参数不对视频文件产生影响。
//            flag：DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC
//            surface：通过mMediaCodec.createInputSurface()获得。
            mediaProjection.createVirtualDisplay("daidai",width,height,2, DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC,inputSurface,null,null);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    @Override
    public void run() {
        // 进入配置阶段完毕
        mediaCodec.start();
        MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
        while (true) {
            // 输入已经被解决了 直接拿输出就行
            int outIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, 10000);
            if (outIndex>=0) {
                // 拿到编码后得数据
                ByteBuffer byteBuffer = mediaCodec.getOutputBuffer(outIndex);
                    byte[] ba = new byte[byteBuffer.remaining()];
                    // 给ba 赋值
                byteBuffer.get(ba);//将容器的byteBuffer  内部的数据 转移到 byte[]中
                writeFile(ba); // 写文件
                mediaCodec.releaseOutputBuffer(outIndex,false);// 刷新数据出去
            }

        }
    }

    private void  writeFile(byte[] ba) {
        // 打开输入流
        String path = Environment.getExternalStorageDirectory().getAbsolutePath()+"/codec.h264";
        FileOutputStream fileOutputStream = null;
        try {
            // append 文件后面
            fileOutputStream = new FileOutputStream(path,true);
            fileOutputStream.write(ba);
        } catch (IOException e) {
            e.printStackTrace();
            if (fileOutputStream!=null) {
                try {
                    fileOutputStream.close();
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        }

    }
}
